using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System;

// 走廊优先地牢生成器，继承自简单随机行走地牢生成器
public class CorridorFirstDungeonGenerator : SimpleRandomWalkDungeonGenerator
{
    [SerializeField, Header("走廊长度")] private int corridorLength = 14;
    [SerializeField, Header("走廊数量")] private int corridorCount = 5;
    [SerializeField, Header("房间占比")][Range(0.1f, 1)] private float roomPercent = 0.8f;

    private Dictionary<Vector2Int, HashSet<Vector2Int>> roomsDictionary = new Dictionary<Vector2Int, HashSet<Vector2Int>>();
    private HashSet<Vector2Int> corridorPositions;

    // 执行过程化生成
    protected override void RunProceduralGeneration()
    {
        ClearRoomData();
        CorridorFirstGeneration();
    }

    // 走廊优先生成方法
    private void CorridorFirstGeneration()
    {

        HashSet<Vector2Int> floorPositions = new HashSet<Vector2Int>();  // 地板位置集合

        HashSet<Vector2Int> potentialRoomPositions = new HashSet<Vector2Int>();// 房间位置集合

        List<List<Vector2Int>> corridors = CreateCorridors(floorPositions, potentialRoomPositions);// 创建走廊

        HashSet<Vector2Int> roomPositions = CreateRooms(potentialRoomPositions);// 创建房间


        List<Vector2Int> dradEnds = FindAllDeadEnds(floorPositions);
        CreateRoomsAtDeadEnd(dradEnds, roomPositions);

        floorPositions.UnionWith(roomPositions);// 将房间位置添加到地板位置集合中


        // 对每条走廊进行遍历，增加走廊的大小并更新地板位置集合
        for (int i = 0; i < corridors.Count; i++)
        {
            // 增加走廊大小的方法 生成3x3走廊
            // corridors[i] = IncreaseCorridorSizeByOne(corridors[i]);//方法1
            corridors[i] = IncreaseCorridorBrush3by3(corridors[i]);//方法2
            // 将更新后的走廊位置添加到地板位置集合中
            floorPositions.UnionWith(corridors[i]);
        }

        tilemapVisualizer.PaintFloorTiles(floorPositions);  // 绘制地板瓦片
        WallGenerator.CreateWalls(floorPositions, tilemapVisualizer);  // 创建墙壁

        //放置物品
        ItemPlacementHelper itemPlacementHelper = new ItemPlacementHelper(floorPositions, roomPositions);
        PropPlacementManager propPlacementManager = FindObjectOfType<PropPlacementManager>();
        propPlacementManager.SetData(itemPlacementHelper);

        propPlacementManager.SetPlayer(itemPlacementHelper);
        
        propPlacementManager.SetEnemy(itemPlacementHelper);
        
    }

    public List<Vector2Int> IncreaseCorridorSizeByOne(List<Vector2Int> corridor)
    {
        List<Vector2Int> newCorridor = new List<Vector2Int>(); // 新走廊坐标的列表
        Vector2Int previousDirection = Vector2Int.zero; // 上一个方向的单位向量

        for (int i = 1; i < corridor.Count; i++) // 遍历走廊坐标列表
        {
            Vector2Int directionFromCell = corridor[i] - corridor[i - 1]; // 获取当前坐标与上一个坐标之间的方向向量

            if (previousDirection != Vector2Int.zero && directionFromCell != previousDirection)
            {
                // 处理转角情况
                for (int x = -1; x < 2; x++)
                {
                    for (int y = -1; y < 2; y++)
                    {
                        newCorridor.Add(corridor[i - 1] + new Vector2Int(x, y)); // 将转角坐标添加到新走廊坐标列表中
                    }
                }
                previousDirection = directionFromCell; // 更新上一个方向的单位向量
            }
            else
            {
                Vector2Int newCorridorTileOffset = GetDirection90From(directionFromCell); // 获取当前方向的90度偏移向量
                newCorridor.Add(corridor[i - 1]); // 添加当前坐标到新走廊坐标列表中
                newCorridor.Add(corridor[i - 1] + newCorridorTileOffset); // 添加当前坐标及偏移向量到新走廊坐标列表中
            }
        }

        return newCorridor; // 返回新走廊坐标的列表
    }

    public List<Vector2Int> IncreaseCorridorBrush3by3(List<Vector2Int> corridor)
    {
        List<Vector2Int> newCorridor = new List<Vector2Int>(); // 新走廊坐标的列表

        for (int i = 1; i < corridor.Count; i++) // 遍历走廊坐标列表
        {
            for (int x = -1; x < 2; x++) // 在x轴方向上遍历-1到1的范围
            {
                for (int y = -1; y < 2; y++) // 在y轴方向上遍历-1到1的范围
                {
                    newCorridor.Add(corridor[i - 1] + new Vector2Int(x, y)); // 将当前坐标的周围九个坐标添加到新走廊坐标列表中
                }
            }
        }

        return newCorridor; // 返回新走廊坐标的列表
    }


    private Vector2Int GetDirection90From(Vector2Int direction)
    {
        if (direction == Vector2Int.up)
        {
            return Vector2Int.right; // 如果输入方向向量是向上的，返回向右的方向向量
        }
        if (direction == Vector2Int.right)
        {
            return Vector2Int.down; // 如果输入方向向量是向右的，返回向下的方向向量
        }
        if (direction == Vector2Int.down)
        {
            return Vector2Int.left; // 如果输入方向向量是向下的，返回向左的方向向量
        }
        if (direction == Vector2Int.left)
        {
            return Vector2Int.up; // 如果输入方向向量是向左的，返回向上的方向向量
        }

        return Vector2Int.zero; // 如果输入方向向量不是上述情况之一，则返回零向量
    }



    // 在死胡同处创建房间的方法
    private void CreateRoomsAtDeadEnd(List<Vector2Int> deadEnds, HashSet<Vector2Int> roomFloors)
    {
        foreach (var position in deadEnds)
        {
            if (roomFloors.Contains(position) == false)
            {
                var room = RunRandomWalk(randomWalkParameters, position);  // 在选定的位置运行随机行走算法以生成房间地板
                roomFloors.UnionWith(room);  // 将房间地板位置添加到房间位置集合中
            }
        }
    }

    // 查找所有死胡同的方法
    private List<Vector2Int> FindAllDeadEnds(HashSet<Vector2Int> floorPositions)
    {
        // 创建一个空的死路位置列表
        List<Vector2Int> deadEnds = new List<Vector2Int>();

        // 对于每个位置，检查其周围的位置数量
        foreach (var position in floorPositions)
        {
            int neighboursCount = 0;
            // 遍历四个基本方向（上下左右），如果相邻位置在floorPositions中，则增加邻居计数
            foreach (var direction in Direction2D.cardinalDirectionsList)
            {
                if (floorPositions.Contains(position + direction))
                {
                    neighboursCount++;
                }
            }
            // 如果邻居计数为1，则将该位置添加到死路列表中
            if (neighboursCount == 1)
            {
                deadEnds.Add(position);
            }
        }
        // 返回所有死路的位置列表
        return deadEnds;
    }

    // 创建走廊的方法
    private List<List<Vector2Int>> CreateCorridors(HashSet<Vector2Int> floorPositions, HashSet<Vector2Int> potentialRoomPositions)
    {
        var currentPosition = startPosition;  // 当前位置设为起始位置

        potentialRoomPositions.Add(currentPosition);// 将当前位置添加到潜在房间位置集合中

        List<List<Vector2Int>> corridors = new List<List<Vector2Int>>(); // 声明并初始化走廊列表

        for (int i = 0; i < corridorCount; i++)  // 循环生成指定数量的走廊
        {
            var corridor = ProceduralGenerationAlgorithms.RandomWalkCorridor(currentPosition, corridorLength);  // 生成随机走廊
            currentPosition = corridor[corridor.Count - 1];  // 更新当前位置为走廊的最后一个位置

            potentialRoomPositions.Add(currentPosition);// 将当前位置添加到潜在房间位置集合中

            floorPositions.UnionWith(corridor);  // 将走廊位置添加到地板位置集合中
            corridors.Add(corridor);
        }

        corridorPositions = new HashSet<Vector2Int>(floorPositions);

        return corridors;
    }

    // 创建房间的方法
    private HashSet<Vector2Int> CreateRooms(HashSet<Vector2Int> potentialRoomPositions)
    {
        HashSet<Vector2Int> roomPositions = new HashSet<Vector2Int>();
        int roomToCreateCount = Mathf.RoundToInt(potentialRoomPositions.Count * roomPercent);// 计算需要创建的房间数量
        // 根据潜在房间位置集合随机选择要创建的房间位置
        List<Vector2Int> roomsToCreate = potentialRoomPositions.OrderBy(x => Guid.NewGuid()).Take(roomToCreateCount).ToList();
        foreach (var roomPosition in roomsToCreate)
        {
            var roomFloor = RunRandomWalk(randomWalkParameters, roomPosition);// 在选定的位置运行随机行走算法以生成房间地板
            SaveRoomData(roomPosition, roomFloor);
            roomPositions.UnionWith(roomFloor);// 将房间地板位置添加到房间位置集合中
        }
        return roomPositions;
    }

    // 清空房间数据字典
    private void ClearRoomData()
    {
        roomsDictionary.Clear();  
    }

    //保存各个获取房间位置信息
    private void SaveRoomData(Vector2Int roomPosition, HashSet<Vector2Int> roomFloor)
    {
        Debug.Log(roomPosition);
        roomsDictionary[roomPosition] = roomFloor;
    }
}

